package com.example.demo.suanfa_heap;

import org.junit.Test;

import java.util.*;

/**
 * @program: java_base
 * @description: Comparator  demo
 * @author: zhouhongtao
 * @happyCreateTime: 2022/02/16 09:55
 */
public class ComparatorDemo {

    @Test
    public void sortComparator(){

        TreeMap<Student,Integer> map = new TreeMap(new MyComparator());
//        map.put(new Student(1, 2),1);
//        map.put(new Student(3, 5),2);
//        map.put(new Student(5, 3),3);
//        map.put(new Student(2, 2),4);

        Student student1 = new Student(1, 2);
        Student student2 = new Student(3, 5);
        Student student3 = new Student(5, 3);
        Student student4 = new Student(2, 2);
        map.put(student1,1);
        map.put(student2,2);
        map.put(student3,3);
        map.put(student4,4);
        Set<Map.Entry<Student, Integer>> entries = map.entrySet();
        for(Map.Entry<Student, Integer> innMap:entries){
            System.out.println("Student id :" +innMap.getKey().id + " value :" +innMap.getValue());
        }


        TreeMap<Student,Integer> map1 = new TreeMap<>((s1,s2)-> s1.id-s2.id);
        map1.put(student1,1);
        map1.put(student2,2);
        map1.put(student3,3);
        map1.put(student4,4);
        map1.forEach((k,v)->{
            System.out.println("Student1 id :" +k.id + " value :" +v);
        });



    }

    class MyComparator implements Comparator<Student>{

        /**
         * Compares its two arguments for order.  Returns a negative integer,
         * zero, or a positive integer as the first argument is less than, equal
         * to, or greater than the second.<p>
         * <p>
         * The implementor must ensure that {@link Integer#signum
         * signum}{@code (compare(x, y)) == -signum(compare(y, x))} for
         * all {@code x} and {@code y}.  (This implies that {@code
         * compare(x, y)} must throw an exception if and only if {@code
         * compare(y, x)} throws an exception.)<p>
         * <p>
         * The implementor must also ensure that the relation is transitive:
         * {@code ((compare(x, y)>0) && (compare(y, z)>0))} implies
         * {@code compare(x, z)>0}.<p>
         * <p>
         * Finally, the implementor must ensure that {@code compare(x,
         * y)==0} implies that {@code signum(compare(x,
         * z))==signum(compare(y, z))} for all {@code z}.
         *
         * @param o1 the first object to be compared.
         * @param o2 the second object to be compared.
         * @return a negative integer, zero, or a positive integer as the
         * first argument is less than, equal to, or greater than the
         * second.
         * @throws NullPointerException if an argument is null and this
         *                              comparator does not permit null arguments
         * @throws ClassCastException   if the arguments' types prevent them from
         *                              being compared by this comparator.
         * @apiNote It is generally the case, but <i>not</i> strictly required that
         * {@code (compare(x, y)==0) == (x.equals(y))}.  Generally speaking,
         * any comparator that violates this condition should clearly indicate
         * this fact.  The recommended language is "Note: this comparator
         * imposes orderings that are inconsistent with equals."
         */
        // 任何比较器：
        // compare方法里，遵循一个统一的规范：
        // 返回负数的时候，认为第一个参数应该排在前面
        // 返回正数的时候，认为第二个参数应该排在前面
        // 返回0的时候，认为无所谓谁放前面
        @Override
        public int compare(Student o1, Student o2) {
            return o1.id-o2.id;
        }
    }
    class Student{
        public int id;
        public int age;
        public String name;

        public Student(int id, int age) {
            this.id = id;
            this.age = age;
            this.name = "";
        }

        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    ", age=" + age +
                    ", name='" + name + '\'' +
                    '}';
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Student student = (Student) o;
            return id == student.id && age == student.age && Objects.equals(name, student.name);
        }

        @Override
        public int hashCode() {
            return Objects.hash(id, age, name);
        }
    }

}
